package com.shijunhao.graduation.service.system.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shijunhao.graduation.exception.SystemRuntimeException;
import com.shijunhao.graduation.service.system.BaseService;
import com.shijunhao.graduation.utils.SpringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.core.ResolvableType;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * @author: shijunhao
 * @date: 2022/3/2 15:14
 * @description:
 */
public class BaseServiceImpl<M extends BaseMapper<T>, T> implements BaseService<T> {

    private M baseMapper;
    private final Class<M> mapperClass;
    private final Class<T> entityClass;

    public BaseServiceImpl() {
        this(null);
    }

    public BaseServiceImpl(M baseMapper) {
        ResolvableType resolvableType = ResolvableType.forClass(ClassUtils.getUserClass(this.getClass())).as(BaseServiceImpl.class);
        this.mapperClass = (Class<M>) resolvableType.getGeneric(0).resolve();
        this.entityClass = (Class<T>) resolvableType.getGeneric(1).resolve();
        this.baseMapper = baseMapper;
    }

    protected BaseServiceImpl<M, T> getCurrentProxy() {
        try {
            return (BaseServiceImpl<M, T>) AopContext.currentProxy();
        } catch (IllegalStateException var2) {
            return this;
        }
    }

    protected M getBaseMapper() {
        if (Objects.isNull(this.baseMapper)) {
            this.baseMapper = SpringUtils.getBean(mapperClass);
        }
        return baseMapper;
    }

    @Override
    public T getById(Long id) {
        return getCurrentProxy().getBaseMapper().selectById(id);
    }

    @Override
    public List<T> listByIds(Long... ids) {
        return listByIds(Arrays.asList(ids));
    }

    @Override
    public List<T> listByIds(Collection<Long> ids) {
        return getCurrentProxy().getBaseMapper().selectBatchIds(ids);
    }

    @Override
    public List<T> listByCondition(Wrapper<T> wrapper) {
        return getCurrentProxy().getBaseMapper().selectList(wrapper);
    }

    @Override
    public Page<T> page(IPage<T> page, Wrapper<T> wrapper) {
        return (Page<T>) getCurrentProxy().getBaseMapper().selectPage(page, wrapper);
    }

    @Override
    public Page<T> page(IPage<T> page) {
        return page(page, new QueryWrapper<>());
    }

    @Override
    public List<T> selectByCondition(Wrapper<T> wrapper) {
        return getCurrentProxy().getBaseMapper().selectList(wrapper);
    }

    @Override
    public T getOne(Wrapper<T> wrapper) {
        return getCurrentProxy().getBaseMapper().selectOne(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertBatch(Collection<T> entities) {
        M mapper = getCurrentProxy().getBaseMapper();
        for (T entity : entities) {
            int insert = mapper.insert(entity);
            if (insert == 0)
                throw new SystemRuntimeException("插入数据失败");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertOne(T entity) {
        int insert = getCurrentProxy().getBaseMapper().insert(entity);
        if (insert == 0)
            throw new SystemRuntimeException("插入数据失败");
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(T entity) {
        int i = getCurrentProxy().getBaseMapper().updateById(entity);
        return i == 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateByIds(Collection<T> entities) {
        for (T entity : entities) {
            int i = getCurrentProxy().getBaseMapper().updateById(entity);
            if (i != 1)
                throw new SystemRuntimeException("更新数据失败");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteById(Long id) {
        int i = getCurrentProxy().getBaseMapper().deleteById(id);
        return i == 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(Collection<Long> ids) {
        int i = getCurrentProxy().getBaseMapper().deleteBatchIds(ids);
        return i != 0;
    }

    @Override
    public boolean deleteByCondition(Wrapper<T> wrapper) {
        int i = getCurrentProxy().getBaseMapper().delete(wrapper);
        return i != 0;
    }

    @Override
    public int selectCount(Wrapper<T> wrapper) {
        return this.getCurrentProxy().getBaseMapper().selectCount(wrapper);
    }


}
